# by 0x9DEFA478


all: build_entry


STYLE_DEFAULT = "\e[0m"
STYLE_BRIGHT = "\e[1m"
STYLE_UNDERLINE = "\e[4m"
STYLE_FLASH = "\e[5m"
STYLE_INVERSE = "\e[7m"
STYLE_INVISABLE = "\e[8m"

COLOR_BLACK_F = "\e[30m"
COLOR_RED_F = "\e[31m"
COLOR_GREEN_F = "\e[32m"
COLOR_YELLOW_F = "\e[33m"
COLOR_BLUE_F = "\e[34m"
COLOR_PURPLE_F = "\e[35m"
COLOR_CYAN_F = "\e[36m"
COLOR_WHITE_F = "\e[37m"
COLOR_BLACK_B = "\e[40m"
COLOR_RED_B = "\e[41m"
COLOR_GREEN_B = "\e[42m"
COLOR_YELLOW_B = "\e[43m"
COLOR_BLUE_B = "\e[44m"
COLOR_PURPLE_B = "\e[45m"
COLOR_CYAN_B = "\e[46m"
COLOR_WHITE_B = "\e[47m"


# ================================================================

BUILD_PREFIX :=

OUT_BasePath := ./build

CC := $(BUILD_PREFIX)gcc
CXX := $(BUILD_PREFIX)g++
AS := $(BUILD_PREFIX)gcc -x assembler-with-cpp
LD := $(BUILD_PREFIX)g++
STRIP := $(BUILD_PREFIX)strip -s
DEFINE_OPTION_PREFIX := -D
UNDEFINE_OPTION_PREFIX := -U
INCLUDE_PATH_OPTION_PREFIX := -iquote
INCLUDE_PATH_PRIOR_OPTION_PREFIX := -I
INCLUDE_PATH_SYSTEM_OPTION_PREFIX := -isystem
LIB_NAME_OPTION_PREFIX := -l
LIB_PATH_OPTION_PREFIX := -L

IS_OUT_MAP := 0

INCLUDE_MK := INCLUDEs.mk
FILE_MK := FILEs.mk

ProjectFolderName := $(notdir $(patsubst %/,%,$(abspath ./)))
OUT_PathName := $(ProjectFolderName)
TargetName := $(ProjectFolderName)
TargetName_Suffix :=

C_Standard :=
CXX_Standard :=

PREPROCESS :=
POSTPROCESS :=
CLEANPROCESS :=

# ================================================================


C_DEFINES :=
C_UNDEFINES :=
CXX_DEFINES :=
CXX_UNDEFINES :=
ASM_DEFINES :=
ASM_UNDEFINES :=

UNIVERSAL_OPTIONS :=
C_CXX_ASM_OPTIONS :=
C_OPTIONS :=
CXX_OPTIONS :=
ASM_OPTIONS :=
LD_OPTIONS :=
OPTIMIZATION :=

INCLUDE_DIRs :=
FILE_DIRs :=
SRC_INCLUDEs :=
SRC_FILEs :=

LIB_NAMEs :=
LIB_SearchPaths :=
C_CXX_IncludePaths :=
C_CXX_PRIOR_IncludePaths :=
C_CXX_SYSTEM_IncludePaths :=
ASM_IncludePaths :=
ASM_PRIOR_IncludePaths :=
ASM_SYSTEM_IncludePaths :=
C_SOURCEs :=
CXX_SOURCEs :=
ASM_SOURCEs :=
OBJ_SOURCEs :=




CMD_LOG := echo -e
define CMD_CreateDir
	mkdir -p $(1)
endef
define CMD_DeleteDir
	rm -fr $(1)
endef
define CMD_CopyFile
	cp -afr  $(patsubst %/,%,$(1))$(if $(3),/$(3),) $(2)
endef
define CMD_CreateDirFileList
	./shell/get_paths.sh $(1) $(if $(2),-d$(2),) $(if $(3),-f$(3),) $(4)
endef




include Target/TargetConfig.mk


OUT_BasePath := $(patsubst %/,%,$(OUT_BasePath))
OUT_BasePath := $(patsubst %\,%,$(OUT_BasePath))
OUT_OBJ_Path := $(OUT_BasePath)/$(OUT_PathName)/obj
OUT_Path := $(OUT_BasePath)/$(OUT_PathName)/bin
OUT_Path_Target := $(OUT_BasePath)/$(OUT_PathName)/target




CMD_PREPROCESS := $(CMD_LOG) $(COLOR_BLUE_F)no preprocess$(STYLE_DEFAULT)
CMD_POSTPROCESS := $(CMD_LOG) $(COLOR_BLUE_F)no postprocess$(STYLE_DEFAULT)
CMD_CLEANPROCESS := $(CMD_LOG) $(COLOR_BLUE_F)no clean process$(STYLE_DEFAULT)
ifneq ($(PREPROCESS),)
CMD_PREPROCESS := $(PREPROCESS)
endif
ifneq ($(POSTPROCESS),)
CMD_POSTPROCESS := $(POSTPROCESS) 
endif
ifneq ($(CLEANPROCESS),)
CMD_CLEANPROCESS := $(CLEANPROCESS)
endif




OUT_Folders :=

# 添加输出路径
OUT_Folders += $(OUT_OBJ_Path) $(OUT_Path) $(OUT_Path_Target)

# 包含需要的文件
sinclude $(OUT_OBJ_Path)/$(INCLUDE_MK)
sinclude $(OUT_OBJ_Path)/$(FILE_MK)


C_BUILD_OPTIONS :=
C_BUILD_OPTIONS += $(addprefix -std=,$(C_Standard))
C_BUILD_OPTIONS += $(UNIVERSAL_OPTIONS) $(C_CXX_ASM_OPTIONS)
C_BUILD_OPTIONS += $(C_OPTIONS) $(OPTIMIZATION)
CXX_BUILD_OPTIONS :=
CXX_BUILD_OPTIONS += $(addprefix -std=,$(CXX_Standard))
CXX_BUILD_OPTIONS += $(UNIVERSAL_OPTIONS) $(C_CXX_ASM_OPTIONS)
CXX_BUILD_OPTIONS += $(CXX_OPTIONS) $(OPTIMIZATION)
ASM_BUILD_OPTIONS :=
ASM_BUILD_OPTIONS += $(UNIVERSAL_OPTIONS) $(C_CXX_ASM_OPTIONS)
ASM_BUILD_OPTIONS += $(ASM_OPTIONS)
LD_BUILD_OPTIONS :=
LD_BUILD_OPTIONS += $(UNIVERSAL_OPTIONS) $(LD_OPTIONS)
ifneq ($(IS_OUT_MAP),0)
LD_BUILD_OPTIONS += -Wl,-Map=$(OUT_Path)/$(TargetName).map,--cref
endif
LD_BUILD_OPTIONS += $(addprefix $(LIB_PATH_OPTION_PREFIX),$(LIB_SearchPaths)) $(addprefix $(LIB_NAME_OPTION_PREFIX),$(LIB_NAMEs))

C_DEFINE_OPTIONS :=
C_DEFINE_OPTIONS += $(addprefix $(DEFINE_OPTION_PREFIX),$(C_CXX_DEFINES) $(C_DEFINES))
C_DEFINE_OPTIONS += $(addprefix $(UNDEFINE_OPTION_PREFIX),$(C_CXX_UNDEFINES) $(C_UNDEFINES))
CXX_DEFINE_OPTIONS :=
CXX_DEFINE_OPTIONS += $(addprefix $(DEFINE_OPTION_PREFIX),$(C_CXX_DEFINES) $(CXX_DEFINES))
CXX_DEFINE_OPTIONS += $(addprefix $(UNDEFINE_OPTION_PREFIX),$(C_CXX_UNDEFINES) $(CXX_UNDEFINES))
ASM_DEFINE_OPTIONS :=
ASM_DEFINE_OPTIONS += $(addprefix $(DEFINE_OPTION_PREFIX),$(ASM_DEFINES))
ASM_DEFINE_OPTIONS += $(addprefix $(UNDEFINE_OPTION_PREFIX),$(ASM_UNDEFINES))

C_CXX_INCLUDE_OPTIONS :=
C_CXX_INCLUDE_OPTIONS += $(addprefix $(INCLUDE_PATH_OPTION_PREFIX),$(C_CXX_IncludePaths) $(SRC_INCLUDEs))
C_CXX_INCLUDE_OPTIONS += $(addprefix $(INCLUDE_PATH_PRIOR_OPTION_PREFIX),$(C_CXX_PRIOR_IncludePaths))
C_CXX_INCLUDE_OPTIONS += $(addprefix $(INCLUDE_PATH_SYSTEM_OPTION_PREFIX),$(C_CXX_SYSTEM_IncludePaths))
ASM_INCLUDE_OPTIONS :=
ASM_INCLUDE_OPTIONS += $(addprefix $(INCLUDE_PATH_OPTION_PREFIX),$(ASM_IncludePaths))
ASM_INCLUDE_OPTIONS += $(addprefix $(INCLUDE_PATH_PRIOR_OPTION_PREFIX),$(ASM_PRIOR_IncludePaths))
ASM_INCLUDE_OPTIONS += $(addprefix $(INCLUDE_PATH_SYSTEM_OPTION_PREFIX),$(ASM_SYSTEM_IncludePaths))


C_SOURCEs += $(filter %.c,$(SRC_FILEs))
CXX_SOURCEs += $(filter %.cpp,$(SRC_FILEs))
ASM_SOURCEs += $(filter %.s %.asm,$(SRC_FILEs))
ASM_SOURCEs_s := $(filter %.s,$(ASM_SOURCEs))
ASM_SOURCEs_asm := $(filter %.asm,$(ASM_SOURCEs))
OBJ_SOURCEs += $(filter %.o %.obj,$(SRC_FILEs))
OBJECTs :=
OBJECTs += $(addprefix $(OUT_OBJ_Path)/,$(addsuffix .o,$(C_SOURCEs)))
OBJECTs += $(addprefix $(OUT_OBJ_Path)/,$(addsuffix .o,$(CXX_SOURCEs)))
OBJECTs += $(addprefix $(OUT_OBJ_Path)/,$(addsuffix .o,$(ASM_SOURCEs_s)))
OBJECTs += $(addprefix $(OUT_OBJ_Path)/,$(addsuffix .o,$(ASM_SOURCEs_asm)))
# 添加目标文件路径
OUT_Folders += $(sort $(dir $(OBJECTs)))




# 头文件mk文件生成
.PHONY: $(OUT_OBJ_Path)/$(INCLUDE_MK)
$(OUT_OBJ_Path)/$(INCLUDE_MK): $(OUT_OBJ_Path)
	@ $(CMD_LOG) $(COLOR_GREEN_F)generate $(OUT_OBJ_Path)/$(INCLUDE_MK)$(STYLE_DEFAULT) $(INCLUDE_DIRs)
	@ $(call CMD_CreateDirFileList,$@,'SRC_INCLUDEs += ',,$(INCLUDE_DIRs))

# 源文件mk文件生成
.PHONY: $(OUT_OBJ_Path)/$(FILE_MK)
$(OUT_OBJ_Path)/$(FILE_MK): $(OUT_OBJ_Path)
	@ $(CMD_LOG) $(COLOR_GREEN_F)generate $(OUT_OBJ_Path)/$(FILE_MK)$(STYLE_DEFAULT) $(FILE_DIRs)
	@ $(call CMD_CreateDirFileList,$@,,'SRC_FILEs += ',$(FILE_DIRs))

src_list_mk: $(OUT_OBJ_Path)/$(INCLUDE_MK) $(OUT_OBJ_Path)/$(FILE_MK)

# 文件夹生成
$(OUT_Folders):
	@ $(CMD_LOG) $(COLOR_GREEN_F)generate $@$(STYLE_DEFAULT)
	@ $(call CMD_CreateDir,$@)

make_directory: $(OUT_Folders)




# c文件编译
$(OUT_OBJ_Path)/%.c.o: %.c
	@ $(CMD_LOG) $(COLOR_YELLOW_F)CC$(STYLE_DEFAULT) $<
	@ $(CC) -c $(C_BUILD_OPTIONS) -MMD -MP -MF"$(@:%.o=%.d)" -Wa,-a,-ad,-alms=$(@:.o=.lst) $(C_DEFINE_OPTIONS) $(C_CXX_INCLUDE_OPTIONS) $< -o $@

# cpp文件编译规则
$(OUT_OBJ_Path)/%.cpp.o: %.cpp
	@ $(CMD_LOG) $(COLOR_CYAN_F)CXX$(STYLE_DEFAULT) $<
	@ $(CXX) -c $(CXX_BUILD_OPTIONS) -MMD -MP -MF"$(@:%.o=%.d)" -Wa,-a,-ad,-alms=$(@:.o=.lst) $(CXX_DEFINE_OPTIONS) $(C_CXX_INCLUDE_OPTIONS) $< -o $@

# s文件编译
$(OUT_OBJ_Path)/%.s.o: %.s
	@ $(CMD_LOG) $(COLOR_PURPLE_F)AS$(STYLE_DEFAULT) $<
	@ $(AS) -c $(ASM_BUILD_OPTIONS) $(ASM_DEFINE_OPTIONS) $(ASM_INCLUDE_OPTIONS) $< -o $@

# asm文件编译
$(OUT_OBJ_Path)/%.asm.o: %.asm
	@ $(CMD_LOG) $(COLOR_PURPLE_F)AS$(STYLE_DEFAULT) $<
	@ $(AS) -c $(ASM_BUILD_OPTIONS) $(ASM_DEFINE_OPTIONS) $(ASM_INCLUDE_OPTIONS) $< -o $@

# 可执行文件生成
$(OUT_Path)/$(TargetName)$(TargetName_Suffix): $(OBJECTs)
	@ $(CMD_LOG) $(COLOR_GREEN_F)LD $@$(STYLE_DEFAULT)
	@ $(LD) $(OBJECTs) $(OBJ_SOURCEs) $(LD_BUILD_OPTIONS) -o $@

$(OUT_Path_Target)/$(TargetName)$(TargetName_Suffix): $(OUT_Path)/$(TargetName)$(TargetName_Suffix)
	@ $(CMD_LOG) $(COLOR_GREEN_F)STRIP $@$(STYLE_DEFAULT)
	@ $(call CMD_CopyFile,$<,$@)
	@ $(STRIP) $@

build_all: $(OUT_Path_Target)/$(TargetName)$(TargetName_Suffix)

build_entry:
	@ $(CMD_LOG) $(COLOR_YELLOW_F)"========   build start   ========"$(STYLE_DEFAULT)
	@ $(CMD_LOG) $(COLOR_CYAN_F)preprocess...$(STYLE_DEFAULT)
	+@ $(CMD_PREPROCESS)
	@ $(CMD_LOG) $(COLOR_CYAN_F)build target: $(TargetName)$(STYLE_DEFAULT)
	@ $(CMD_LOG) $(COLOR_GREEN_B)analysis path$(STYLE_DEFAULT)
	+@ $(MAKE) src_list_mk
	+@ $(MAKE) make_directory
	@ $(CMD_LOG) $(COLOR_GREEN_B)Info$(STYLE_DEFAULT)
	+@ $(MAKE) info
	@ $(CMD_LOG) $(COLOR_GREEN_B)build$(STYLE_DEFAULT)
	+@ $(MAKE) build_all
	@ $(CMD_LOG) $(COLOR_YELLOW_F)"======== build completed ========"$(STYLE_DEFAULT)
	@ $(CMD_LOG) $(COLOR_CYAN_F)postprocess...$(STYLE_DEFAULT)
	+@ $(CMD_POSTPROCESS)
	@ $(CMD_LOG) $(COLOR_YELLOW_F)"========  all completed  ========"$(STYLE_DEFAULT)

clean:
	@ $(CMD_LOG) $(COLOR_YELLOW_F)"========   clean start   ========"$(STYLE_DEFAULT)
	@ $(CMD_LOG) $(COLOR_PURPLE_F)clean process...$(STYLE_DEFAULT)
	@ $(CMD_CLEANPROCESS)
	@ $(CMD_LOG) $(COLOR_PURPLE_F)delete dir $(OUT_OBJ_Path)$(STYLE_DEFAULT)
	-@ $(call CMD_DeleteDir,$(OUT_OBJ_Path))
	@ $(CMD_LOG) $(COLOR_YELLOW_F)"======== clean completed ========"$(STYLE_DEFAULT)

.PHONY: info
info:
	@ $(CMD_LOG) $(COLOR_BLUE_F)compiler$(STYLE_DEFAULT) $(BUILD_PREFIX)g++ $(BUILD_PREFIX)gcc "\n"\
$(COLOR_BLUE_F)Target$(STYLE_DEFAULT) $(OUT_Path)/$(TargetName)$(TargetName_Suffix) "\n"\
$(COLOR_BLUE_F)C_DEFINE_OPTIONS$(STYLE_DEFAULT) $(C_DEFINE_OPTIONS) "\n"\
$(COLOR_BLUE_F)CXX_DEFINE_OPTIONS$(STYLE_DEFAULT) $(CXX_DEFINE_OPTIONS) "\n"\
$(COLOR_BLUE_F)ASM_DEFINE_OPTIONS$(STYLE_DEFAULT) $(ASM_DEFINE_OPTIONS) "\n"\
$(COLOR_BLUE_F)C_CXX_INCLUDE_OPTIONS$(STYLE_DEFAULT) $(C_CXX_INCLUDE_OPTIONS) "\n"\
$(COLOR_BLUE_F)ASM_INCLUDE_OPTIONS$(STYLE_DEFAULT) $(ASM_INCLUDE_OPTIONS) "\n"\
$(COLOR_BLUE_F)C_BUILD_OPTIONS$(STYLE_DEFAULT) $(C_BUILD_OPTIONS) "\n"\
$(COLOR_BLUE_F)CXX_BUILD_OPTIONS$(STYLE_DEFAULT) $(CXX_BUILD_OPTIONS) "\n"\
$(COLOR_BLUE_F)ASM_BUILD_OPTIONS$(STYLE_DEFAULT) $(ASM_BUILD_OPTIONS) "\n"\
$(COLOR_BLUE_F)LD_BUILD_OPTIONS$(STYLE_DEFAULT) $(LD_BUILD_OPTIONS) "\n"




sinclude $(OBJECTs:.o=.d)



